
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_Hans">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>模型实例参考 &#8212; Django 3.2.6.dev 文档</title>
    <link rel="stylesheet" href="../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
    <script type="text/javascript" id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../_static/language_data.js"></script>
    <link rel="index" title="索引" href="../../genindex.html" />
    <link rel="search" title="搜索" href="../../search.html" />
    <link rel="next" title="QuerySet API 参考" href="querysets.html" />
    <link rel="prev" title="模型 Meta 选项" href="options.html" />



 
<script src="../../templatebuiltins.js"></script>
<script>
(function($) {
    if (!django_template_builtins) {
       // templatebuiltins.js missing, do nothing.
       return;
    }
    $(document).ready(function() {
        // Hyperlink Django template tags and filters
        var base = "../templates/builtins.html";
        if (base == "#") {
            // Special case for builtins.html itself
            base = "";
        }
        // Tags are keywords, class '.k'
        $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
             var tagname = $(elem).text();
             if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
                 var fragment = tagname.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
             }
        });
        // Filters are functions, class '.nf'
        $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
             var filtername = $(elem).text();
             if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
                 var fragment = filtername.replace(/_/, '-');
                 $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
             }
        });
    });
})(jQuery);</script>

  </head><body>

    <div class="document">
  <div id="custom-doc" class="yui-t6">
    <div id="hd">
      <h1><a href="../../index.html">Django 3.2.6.dev 文档</a></h1>
      <div id="global-nav">
        <a title="Home page" href="../../index.html">Home</a>  |
        <a title="Table of contents" href="../../contents.html">Table of contents</a>  |
        <a title="Global index" href="../../genindex.html">Index</a>  |
        <a title="Module index" href="../../py-modindex.html">Modules</a>
      </div>
      <div class="nav">
    &laquo; <a href="options.html" title="模型 &lt;code class=&#34;docutils literal notranslate&#34;&gt;&lt;span class=&#34;pre&#34;&gt;Meta&lt;/span&gt;&lt;/code&gt; 选项">previous</a>
     |
    <a href="../index.html" title="API 参考" accesskey="U">up</a>
   |
    <a href="querysets.html" title="&lt;code class=&#34;docutils literal notranslate&#34;&gt;&lt;span class=&#34;pre&#34;&gt;QuerySet&lt;/span&gt;&lt;/code&gt; API 参考">next</a> &raquo;</div>
    </div>

    <div id="bd">
      <div id="yui-main">
        <div class="yui-b">
          <div class="yui-g" id="ref-models-instances">
            
  <div class="section" id="s-model-instance-reference">
<span id="model-instance-reference"></span><h1>模型实例参考<a class="headerlink" href="#model-instance-reference" title="永久链接至标题">¶</a></h1>
<p>本文档描述了 <code class="docutils literal notranslate"><span class="pre">Model</span></code> API 的细节。它建立在 <a class="reference internal" href="../../topics/db/models.html"><span class="doc">模型</span></a> 和 <a class="reference internal" href="../../topics/db/queries.html"><span class="doc">数据库查询</span></a> 指南中所介绍的材料基础上，因此，在阅读本文档之前，你可能需要阅读并理解这些文档。</p>
<p>在整篇参考中，我们将使用 <a class="reference internal" href="../../topics/db/queries.html"><span class="doc">数据库查询指南</span></a> 中的 <a class="reference internal" href="../../topics/db/queries.html#queryset-model-example"><span class="std std-ref">Weblog 示例模型</span></a> 。</p>
<div class="section" id="s-creating-objects">
<span id="creating-objects"></span><h2>创建对象<a class="headerlink" href="#creating-objects" title="永久链接至标题">¶</a></h2>
<p>要创建一个新的模型实例，像其他 Python 类一样实例化它。</p>
<dl class="class">
<dt id="django.db.models.Model">
<em class="property">class </em><code class="descname">Model</code>(<em>**kwargs</em>)<a class="headerlink" href="#django.db.models.Model" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>关键字参数是你在模型上定义的字段名。请注意，实例化一个模型不会触及你的数据库；为此，你需要 <a class="reference internal" href="#django.db.models.Model.save" title="django.db.models.Model.save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a>。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p>你可能会想通过覆盖 <code class="docutils literal notranslate"><span class="pre">__init__</span></code> 方法来定制模型。但是，如果你这样做，请注意不要更改调用签名，因为任何更改都可能阻止模型实例被保存。与其覆盖 <code class="docutils literal notranslate"><span class="pre">__init__</span></code>，不如尝试使用以下方法之一：</p>
<ol class="last arabic">
<li><p class="first">在模型类上增加一个类方法：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Book</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">title</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>

    <span class="nd">@classmethod</span>
    <span class="k">def</span> <span class="nf">create</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">title</span><span class="p">):</span>
        <span class="n">book</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="n">title</span><span class="p">)</span>
        <span class="c1"># do something with the book</span>
        <span class="k">return</span> <span class="n">book</span>

<span class="n">book</span> <span class="o">=</span> <span class="n">Book</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="s2">&quot;Pride and Prejudice&quot;</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p class="first">在自定义管理器上添加一个方法（通常首选）：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">BookManager</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Manager</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">create_book</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">):</span>
        <span class="n">book</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="n">title</span><span class="p">)</span>
        <span class="c1"># do something with the book</span>
        <span class="k">return</span> <span class="n">book</span>

<span class="k">class</span> <span class="nc">Book</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">title</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>

    <span class="n">objects</span> <span class="o">=</span> <span class="n">BookManager</span><span class="p">()</span>

<span class="n">book</span> <span class="o">=</span> <span class="n">Book</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create_book</span><span class="p">(</span><span class="s2">&quot;Pride and Prejudice&quot;</span><span class="p">)</span>
</pre></div>
</div>
</li>
</ol>
</div>
<div class="section" id="s-customizing-model-loading">
<span id="customizing-model-loading"></span><h3>自定义模型加载<a class="headerlink" href="#customizing-model-loading" title="永久链接至标题">¶</a></h3>
<dl class="classmethod">
<dt id="django.db.models.Model.from_db">
<em class="property">classmethod </em><code class="descclassname">Model.</code><code class="descname">from_db</code>(<em>db</em>, <em>field_names</em>, <em>values</em>)<a class="headerlink" href="#django.db.models.Model.from_db" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p><code class="docutils literal notranslate"><span class="pre">from_db()</span></code> 方法可以在数据库加载时用于自定义模型实例创建。</p>
<p><code class="docutils literal notranslate"><span class="pre">db</span></code> 参数包含模型从数据库加载的数据库别名，<code class="docutils literal notranslate"><span class="pre">field_names</span></code> 包含所有加载字段的名称，<code class="docutils literal notranslate"><span class="pre">values</span></code> 包含 <code class="docutils literal notranslate"><span class="pre">field_names</span></code> 中每个字段的加载值。<code class="docutils literal notranslate"><span class="pre">field_names</span></code> 和 <code class="docutils literal notranslate"><span class="pre">values</span></code> 的顺序相同。如果模型的所有字段都存在，那么 <code class="docutils literal notranslate"><span class="pre">values</span></code> 就必须按照 <code class="docutils literal notranslate"><span class="pre">__init__()</span></code> 预期的顺序。也就是说，实例可以通过 <code class="docutils literal notranslate"><span class="pre">cls(*values)</span></code> 来创建。如果有任何字段被推迟，它们将不会出现在 <code class="docutils literal notranslate"><span class="pre">field_names</span></code> 中。在这种情况下，给每个缺失的字段分配一个 <code class="docutils literal notranslate"><span class="pre">django.db.models.DEFERRED</span></code> 的值。</p>
<p>除了创建新的模型外，<code class="docutils literal notranslate"><span class="pre">from_db()</span></code> 方法必须在新实例的 <a class="reference internal" href="#django.db.models.Model._state" title="django.db.models.Model._state"><code class="xref py py-attr docutils literal notranslate"><span class="pre">_state</span></code></a> 属性中设置 <code class="docutils literal notranslate"><span class="pre">adding</span></code> 和 <code class="docutils literal notranslate"><span class="pre">db</span></code> 标志。</p>
<p>下面是一个例子，说明如何记录从数据库中加载字段的初始值：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">DEFERRED</span>

<span class="nd">@classmethod</span>
<span class="k">def</span> <span class="nf">from_db</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">db</span><span class="p">,</span> <span class="n">field_names</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
    <span class="c1"># Default implementation of from_db() (subject to change and could</span>
    <span class="c1"># be replaced with super()).</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span><span class="p">):</span>
        <span class="n">values</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
        <span class="n">values</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>
        <span class="n">values</span> <span class="o">=</span> <span class="p">[</span>
            <span class="n">values</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">attname</span> <span class="ow">in</span> <span class="n">field_names</span> <span class="k">else</span> <span class="n">DEFERRED</span>
            <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">_meta</span><span class="o">.</span><span class="n">concrete_fields</span>
        <span class="p">]</span>
    <span class="n">instance</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span><span class="o">*</span><span class="n">values</span><span class="p">)</span>
    <span class="n">instance</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span> <span class="o">=</span> <span class="kc">False</span>
    <span class="n">instance</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
    <span class="c1"># customization to store the original field values on the instance</span>
    <span class="n">instance</span><span class="o">.</span><span class="n">_loaded_values</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">field_names</span><span class="p">,</span> <span class="n">values</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">instance</span>

<span class="k">def</span> <span class="nf">save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="c1"># Check how the current values differ from ._loaded_values. For example,</span>
    <span class="c1"># prevent changing the creator_id of the model. (This example doesn&#39;t</span>
    <span class="c1"># support cases where &#39;creator_id&#39; is deferred).</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span><span class="o">.</span><span class="n">adding</span> <span class="ow">and</span> <span class="p">(</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">creator_id</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_loaded_values</span><span class="p">[</span><span class="s1">&#39;creator_id&#39;</span><span class="p">]):</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Updating the value of creator isn&#39;t allowed&quot;</span><span class="p">)</span>
    <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</div>
<p>上面的例子显示了一个完整的 <code class="docutils literal notranslate"><span class="pre">from_db()</span></code> 实现，以说明如何做到这一点。在这种情况下，可以在 <code class="docutils literal notranslate"><span class="pre">from_db()</span></code> 方法中使用 <code class="docutils literal notranslate"><span class="pre">super()</span></code> 调用。</p>
</div>
</div>
<div class="section" id="s-refreshing-objects-from-database">
<span id="refreshing-objects-from-database"></span><h2>从数据库中刷新对象<a class="headerlink" href="#refreshing-objects-from-database" title="永久链接至标题">¶</a></h2>
<p>如果你从模型实例中删除了一个字段，再次访问它就会从数据库中重新加载该值：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">obj</span> <span class="o">=</span> <span class="n">MyModel</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">obj</span><span class="o">.</span><span class="n">field</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">obj</span><span class="o">.</span><span class="n">field</span>  <span class="c1"># Loads the field from the database</span>
</pre></div>
</div>
<dl class="method">
<dt id="django.db.models.Model.refresh_from_db">
<code class="descclassname">Model.</code><code class="descname">refresh_from_db</code>(<em>using=None</em>, <em>fields=None</em>)<a class="headerlink" href="#django.db.models.Model.refresh_from_db" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>如果你需要从数据库中重新加载一个模型的值，你可以使用 <code class="docutils literal notranslate"><span class="pre">refresh_from_db()</span></code> 方法。当这个方法被调用时，没有参数时，会做以下工作：</p>
<ol class="arabic simple">
<li>模型的所有非递延字段都更新为数据库中当前的值。</li>
<li>任何缓存的关系都会从重新加载的实例中清除。</li>
</ol>
<p>只有模型的字段会从数据库中重载。其他依赖于数据库的值，如注释，不会被重载。任何 <a class="reference internal" href="../utils.html#django.utils.functional.cached_property" title="django.utils.functional.cached_property"><code class="xref py py-func docutils literal notranslate"><span class="pre">&#64;cached_property</span></code></a> 属性也不会被清除。</p>
<p>重载发生在实例被加载的数据库中，如果实例不是从数据库中加载的，则从默认数据库中加载。<code class="docutils literal notranslate"><span class="pre">using</span></code> 参数可以用来强制使用数据库进行重载。</p>
<p>可以通过使用 <code class="docutils literal notranslate"><span class="pre">fields</span></code> 参数强制加载一组字段。</p>
<p>例如，为了测试 <code class="docutils literal notranslate"><span class="pre">update()</span></code> 的调用是否导致了预期的更新，你可以写一个类似这样的测试：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">test_update_result</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">obj</span> <span class="o">=</span> <span class="n">MyModel</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">val</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
    <span class="n">MyModel</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">pk</span><span class="o">=</span><span class="n">obj</span><span class="o">.</span><span class="n">pk</span><span class="p">)</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">val</span><span class="o">=</span><span class="n">F</span><span class="p">(</span><span class="s1">&#39;val&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
    <span class="c1"># At this point obj.val is still 1, but the value in the database</span>
    <span class="c1"># was updated to 2. The object&#39;s updated value needs to be reloaded</span>
    <span class="c1"># from the database.</span>
    <span class="n">obj</span><span class="o">.</span><span class="n">refresh_from_db</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">val</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</pre></div>
</div>
<p>请注意，当访问递延字段时，递延字段的值的加载是通过这个方法发生的。因此，可以自定义递延加载的发生方式。下面的例子显示了当一个递延字段被重载时，如何重载实例的所有字段：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">ExampleModel</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">refresh_from_db</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">using</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">fields</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="c1"># fields contains the name of the deferred field to be</span>
        <span class="c1"># loaded.</span>
        <span class="k">if</span> <span class="n">fields</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">fields</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span>
            <span class="n">deferred_fields</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_deferred_fields</span><span class="p">()</span>
            <span class="c1"># If any deferred field is going to be loaded</span>
            <span class="k">if</span> <span class="n">fields</span><span class="o">.</span><span class="n">intersection</span><span class="p">(</span><span class="n">deferred_fields</span><span class="p">):</span>
                <span class="c1"># then load all of them</span>
                <span class="n">fields</span> <span class="o">=</span> <span class="n">fields</span><span class="o">.</span><span class="n">union</span><span class="p">(</span><span class="n">deferred_fields</span><span class="p">)</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">refresh_from_db</span><span class="p">(</span><span class="n">using</span><span class="p">,</span> <span class="n">fields</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</div>
<dl class="method">
<dt id="django.db.models.Model.get_deferred_fields">
<code class="descclassname">Model.</code><code class="descname">get_deferred_fields</code>()<a class="headerlink" href="#django.db.models.Model.get_deferred_fields" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>一个辅助方法，返回一个包含当前这个模型的所有这些字段的属性名的集合。</p>
</div>
<div class="section" id="s-validating-objects">
<span id="s-id1"></span><span id="validating-objects"></span><span id="id1"></span><h2>验证对象<a class="headerlink" href="#validating-objects" title="永久链接至标题">¶</a></h2>
<p>验证一个模型有三个步骤：</p>
<ol class="arabic simple">
<li>验证模型字段—— <a class="reference internal" href="#django.db.models.Model.clean_fields" title="django.db.models.Model.clean_fields"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.clean_fields()</span></code></a></li>
<li>验证整个模型—— <a class="reference internal" href="#django.db.models.Model.clean" title="django.db.models.Model.clean"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.clean()</span></code></a></li>
<li>验证字段的唯一性—— <a class="reference internal" href="#django.db.models.Model.validate_unique" title="django.db.models.Model.validate_unique"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.validate_unique()</span></code></a></li>
</ol>
<p>当你调用一个模型的 <a class="reference internal" href="#django.db.models.Model.full_clean" title="django.db.models.Model.full_clean"><code class="xref py py-meth docutils literal notranslate"><span class="pre">full_clean()</span></code></a> 方法时，这三个步骤都会被执行。</p>
<p>当你使用一个 <a class="reference internal" href="../../topics/forms/modelforms.html#django.forms.ModelForm" title="django.forms.ModelForm"><code class="xref py py-class docutils literal notranslate"><span class="pre">ModelForm</span></code></a> 时，调用 <a class="reference internal" href="../forms/api.html#django.forms.Form.is_valid" title="django.forms.Form.is_valid"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_valid()</span></code></a> 将对表单中包含的所有字段执行这些验证步骤。更多信息请参见 <a class="reference internal" href="../../topics/forms/modelforms.html"><span class="doc">模型表单文档</span></a>。只有当你打算自己处理验证错误，或者你从 <a class="reference internal" href="../../topics/forms/modelforms.html#django.forms.ModelForm" title="django.forms.ModelForm"><code class="xref py py-class docutils literal notranslate"><span class="pre">ModelForm</span></code></a> 中排除了需要验证的字段时，才需要调用模型的 <a class="reference internal" href="#django.db.models.Model.full_clean" title="django.db.models.Model.full_clean"><code class="xref py py-meth docutils literal notranslate"><span class="pre">full_clean()</span></code></a> 方法。</p>
<dl class="method">
<dt id="django.db.models.Model.full_clean">
<code class="descclassname">Model.</code><code class="descname">full_clean</code>(<em>exclude=None</em>, <em>validate_unique=True</em>)<a class="headerlink" href="#django.db.models.Model.full_clean" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>这个方法依次调用 <a class="reference internal" href="#django.db.models.Model.clean_fields" title="django.db.models.Model.clean_fields"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.clean_fields()</span></code></a>、 <a class="reference internal" href="#django.db.models.Model.clean" title="django.db.models.Model.clean"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.clean()</span></code></a> 和 <a class="reference internal" href="#django.db.models.Model.validate_unique" title="django.db.models.Model.validate_unique"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.validate_unique()</span></code></a> （如果 <code class="docutils literal notranslate"><span class="pre">validate_unique</span></code> 为 <code class="docutils literal notranslate"><span class="pre">True</span></code>），并引发一个 <a class="reference internal" href="../exceptions.html#django.core.exceptions.ValidationError" title="django.core.exceptions.ValidationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValidationError</span></code></a>，该方法的 <code class="docutils literal notranslate"><span class="pre">message_dict</span></code> 属性包含了所有三个阶段的错误。</p>
<p>可选的 <code class="docutils literal notranslate"><span class="pre">exclude</span></code> 参数可以用来提供一个可以从验证和清理中排除的字段名列表。 <a class="reference internal" href="../../topics/forms/modelforms.html#django.forms.ModelForm" title="django.forms.ModelForm"><code class="xref py py-class docutils literal notranslate"><span class="pre">ModelForm</span></code></a> 使用这个参数来排除那些不存在于你的表单中的字段进行验证，因为任何引发的错误都无法被用户纠正。</p>
<p>请注意，当您调用模型的 <a class="reference internal" href="#django.db.models.Model.save" title="django.db.models.Model.save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a> 方法时，<code class="docutils literal notranslate"><span class="pre">full_clean()</span></code> <em>不会</em> 自动调用。当你想为自己手动创建的模型运行一步模型验证时，你需要手动调用它。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.core.exceptions</span> <span class="kn">import</span> <span class="n">ValidationError</span>
<span class="k">try</span><span class="p">:</span>
    <span class="n">article</span><span class="o">.</span><span class="n">full_clean</span><span class="p">()</span>
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
    <span class="c1"># Do something based on the errors contained in e.message_dict.</span>
    <span class="c1"># Display them to a user, or handle them programmatically.</span>
    <span class="k">pass</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">full_clean()</span></code> 执行的第一步是清理每个单独的字段。</p>
<dl class="method">
<dt id="django.db.models.Model.clean_fields">
<code class="descclassname">Model.</code><code class="descname">clean_fields</code>(<em>exclude=None</em>)<a class="headerlink" href="#django.db.models.Model.clean_fields" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>这个方法将验证你模型上的所有字段。可选的 <code class="docutils literal notranslate"><span class="pre">exclude</span></code> 参数让你提供一个要从验证中排除的字段名列表。如果有任何字段没有通过验证，它将引发一个 <a class="reference internal" href="../exceptions.html#django.core.exceptions.ValidationError" title="django.core.exceptions.ValidationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValidationError</span></code></a>。</p>
<p><code class="docutils literal notranslate"><span class="pre">full_clean()</span></code> 执行的第二步是调用 <a class="reference internal" href="#django.db.models.Model.clean" title="django.db.models.Model.clean"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.clean()</span></code></a>。这个方法应该被重写，以便对你的模型进行自定义验证。</p>
<dl class="method">
<dt id="django.db.models.Model.clean">
<code class="descclassname">Model.</code><code class="descname">clean</code>()<a class="headerlink" href="#django.db.models.Model.clean" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>这个方法应该用来提供自定义模型验证，如果需要的话，还可以修改模型上的属性。例如，你可以使用它来自动为一个字段提供一个值，或进行需要访问多个字段的验证：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">datetime</span>
<span class="kn">from</span> <span class="nn">django.core.exceptions</span> <span class="kn">import</span> <span class="n">ValidationError</span>
<span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext_lazy</span> <span class="k">as</span> <span class="n">_</span>

<span class="k">class</span> <span class="nc">Article</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="o">...</span>
    <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># Don&#39;t allow draft entries to have a pub_date.</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">&#39;draft&#39;</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">pub_date</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;Draft entries may not have a publication date.&#39;</span><span class="p">))</span>
        <span class="c1"># Set the pub_date for published items if it hasn&#39;t been set already.</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">&#39;published&#39;</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">pub_date</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pub_date</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span>
</pre></div>
</div>
<p>但请注意，像 <a class="reference internal" href="#django.db.models.Model.full_clean" title="django.db.models.Model.full_clean"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.full_clean()</span></code></a> 一样，当你调用你的模型的 <a class="reference internal" href="#django.db.models.Model.save" title="django.db.models.Model.save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a> 方法时，模型的 <code class="docutils literal notranslate"><span class="pre">clean()</span></code> 方法不会被调用。</p>
<p>在上面的例子中，由 <code class="docutils literal notranslate"><span class="pre">Model.clean()</span></code> 引发的 <a class="reference internal" href="../exceptions.html#django.core.exceptions.ValidationError" title="django.core.exceptions.ValidationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValidationError</span></code></a> 异常是用字符串实例化的，所以它将被存储在一个特殊的错误字典键中， <a class="reference internal" href="../exceptions.html#django.core.exceptions.NON_FIELD_ERRORS" title="django.core.exceptions.NON_FIELD_ERRORS"><code class="xref py py-data docutils literal notranslate"><span class="pre">NON_FIELD_ERRORS</span></code></a>。这个键用于与整个模型相关的错误，而不是与某个特定字段相关的错误：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.core.exceptions</span> <span class="kn">import</span> <span class="n">NON_FIELD_ERRORS</span><span class="p">,</span> <span class="n">ValidationError</span>
<span class="k">try</span><span class="p">:</span>
    <span class="n">article</span><span class="o">.</span><span class="n">full_clean</span><span class="p">()</span>
<span class="k">except</span> <span class="n">ValidationError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
    <span class="n">non_field_errors</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">message_dict</span><span class="p">[</span><span class="n">NON_FIELD_ERRORS</span><span class="p">]</span>
</pre></div>
</div>
<p>要将异常分配给一个特定的字段，用一个字典实例化 <a class="reference internal" href="../exceptions.html#django.core.exceptions.ValidationError" title="django.core.exceptions.ValidationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValidationError</span></code></a>，其中键是字段名。我们可以更新前面的例子，将错误分配给 <code class="docutils literal notranslate"><span class="pre">pub_date</span></code> 字段：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Article</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="o">...</span>
    <span class="k">def</span> <span class="nf">clean</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># Don&#39;t allow draft entries to have a pub_date.</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">&#39;draft&#39;</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">pub_date</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">({</span><span class="s1">&#39;pub_date&#39;</span><span class="p">:</span> <span class="n">_</span><span class="p">(</span><span class="s1">&#39;Draft entries may not have a publication date.&#39;</span><span class="p">)})</span>
        <span class="o">...</span>
</pre></div>
</div>
<p>如果你在 <code class="docutils literal notranslate"><span class="pre">Model.clean()</span></code> 期间检测到多个字段的错误，你也可以传递一个字段名与错误映射的字典：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">raise</span> <span class="n">ValidationError</span><span class="p">({</span>
    <span class="s1">&#39;title&#39;</span><span class="p">:</span> <span class="n">ValidationError</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;Missing title.&#39;</span><span class="p">),</span> <span class="n">code</span><span class="o">=</span><span class="s1">&#39;required&#39;</span><span class="p">),</span>
    <span class="s1">&#39;pub_date&#39;</span><span class="p">:</span> <span class="n">ValidationError</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">&#39;Invalid date.&#39;</span><span class="p">),</span> <span class="n">code</span><span class="o">=</span><span class="s1">&#39;invalid&#39;</span><span class="p">),</span>
<span class="p">})</span>
</pre></div>
</div>
<p>最后，<code class="docutils literal notranslate"><span class="pre">full_clean()</span></code> 将检查你模型上的任何唯一约束。</p>
<div class="admonition-how-to-raise-field-specific-validation-errors-if-those-fields-don-t-appear-in-a-modelform admonition">
<p class="first admonition-title">如果字段没有出现在 <code class="docutils literal notranslate"><span class="pre">ModelForm</span></code> 中，如何引发特定字段的验证错误。</p>
<p>你不能在 <code class="docutils literal notranslate"><span class="pre">Model.clean()</span></code> 中对没有出现在模型表单中的字段提出验证错误（一个表单可以使用 <code class="docutils literal notranslate"><span class="pre">Meta.field</span></code> 或 <code class="docutils literal notranslate"><span class="pre">Meta.exclude</span></code> 来限制它的字段）。这样做会引发一个 <code class="docutils literal notranslate"><span class="pre">ValueError</span></code>，因为验证错误将无法与被排除的字段相关联。</p>
<p>为了解决这个难题，可以覆盖 <a class="reference internal" href="#django.db.models.Model.clean_fields" title="django.db.models.Model.clean_fields"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Model.clean_fields()</span></code></a>，因为它接收的是被排除在验证之外的字段列表。例如：</p>
<div class="last highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Article</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="o">...</span>
    <span class="k">def</span> <span class="nf">clean_fields</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exclude</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">clean_fields</span><span class="p">(</span><span class="n">exclude</span><span class="o">=</span><span class="n">exclude</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">&#39;draft&#39;</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">pub_date</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">exclude</span> <span class="ow">and</span> <span class="s1">&#39;status&#39;</span> <span class="ow">in</span> <span class="n">exclude</span><span class="p">:</span>
                <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">(</span>
                    <span class="n">_</span><span class="p">(</span><span class="s1">&#39;Draft entries may not have a publication date.&#39;</span><span class="p">)</span>
                <span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">raise</span> <span class="n">ValidationError</span><span class="p">({</span>
                    <span class="s1">&#39;status&#39;</span><span class="p">:</span> <span class="n">_</span><span class="p">(</span>
                        <span class="s1">&#39;Set status to draft if there is not a &#39;</span>
                        <span class="s1">&#39;publication date.&#39;</span>
                     <span class="p">),</span>
                <span class="p">})</span>
</pre></div>
</div>
</div>
<dl class="method">
<dt id="django.db.models.Model.validate_unique">
<code class="descclassname">Model.</code><code class="descname">validate_unique</code>(<em>exclude=None</em>)<a class="headerlink" href="#django.db.models.Model.validate_unique" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>这个方法类似于 <a class="reference internal" href="#django.db.models.Model.clean_fields" title="django.db.models.Model.clean_fields"><code class="xref py py-meth docutils literal notranslate"><span class="pre">clean_fields()</span></code></a>，但验证的是模型上所有的唯一性约束，而不是单个字段值。可选的 <code class="docutils literal notranslate"><span class="pre">exclude</span></code> 参数允许你提供一个要从验证中排除的字段名列表。如果任何字段验证失败，它将引发一个 <a class="reference internal" href="../exceptions.html#django.core.exceptions.ValidationError" title="django.core.exceptions.ValidationError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValidationError</span></code></a>。</p>
<p>请注意，如果你为 <code class="docutils literal notranslate"><span class="pre">validate_unique()</span></code> 提供了一个 <code class="docutils literal notranslate"><span class="pre">exclude</span></code> 参数，任何涉及你提供的一个字段的 <a class="reference internal" href="options.html#django.db.models.Options.unique_together" title="django.db.models.Options.unique_together"><code class="xref py py-attr docutils literal notranslate"><span class="pre">unique_together</span></code></a> 约束将不会被检查。</p>
</div>
<div class="section" id="s-saving-objects">
<span id="saving-objects"></span><h2>保存对象<a class="headerlink" href="#saving-objects" title="永久链接至标题">¶</a></h2>
<p>要将对象保存回数据库，调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code>：</p>
<dl class="method">
<dt id="django.db.models.Model.save">
<code class="descclassname">Model.</code><code class="descname">save</code>(<em>force_insert=False</em>, <em>force_update=False</em>, <em>using=DEFAULT_DB_ALIAS</em>, <em>update_fields=None</em>)<a class="headerlink" href="#django.db.models.Model.save" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>如果你想自定义保存行为，你可以覆盖这个 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法。更多细节请参见 <a class="reference internal" href="../../topics/db/models.html#overriding-model-methods"><span class="std std-ref">Overriding predefined model methods</span></a>。</p>
<p>模型保存过程也有一些微妙的地方，请看下面的章节。</p>
<div class="section" id="s-auto-incrementing-primary-keys">
<span id="auto-incrementing-primary-keys"></span><h3>自增主键<a class="headerlink" href="#auto-incrementing-primary-keys" title="永久链接至标题">¶</a></h3>
<p>如果一个模型有一个 <a class="reference internal" href="fields.html#django.db.models.AutoField" title="django.db.models.AutoField"><code class="xref py py-class docutils literal notranslate"><span class="pre">AutoField</span></code></a>——一个自动递增的主键，那么当你第一次调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 时，这个自动递增的值就会被计算出来并保存为你的对象的一个属性：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">b2</span> <span class="o">=</span> <span class="n">Blog</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Cheddar Talk&#39;</span><span class="p">,</span> <span class="n">tagline</span><span class="o">=</span><span class="s1">&#39;Thoughts on cheese.&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b2</span><span class="o">.</span><span class="n">id</span>     <span class="c1"># Returns None, because b2 doesn&#39;t have an ID yet.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b2</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b2</span><span class="o">.</span><span class="n">id</span>     <span class="c1"># Returns the ID of your new object.</span>
</pre></div>
</div>
<p>在你调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 之前，没有办法知道一个 ID 的值是多少，因为这个值是由你的数据库计算出来的，而不是由 Django 计算出来的。</p>
<p>为了方便起见，每个模型都有一个 <a class="reference internal" href="fields.html#django.db.models.AutoField" title="django.db.models.AutoField"><code class="xref py py-class docutils literal notranslate"><span class="pre">AutoField</span></code></a> 默认命名为 <code class="docutils literal notranslate"><span class="pre">id</span></code>，除非你在模型中的字段上明确指定 <code class="docutils literal notranslate"><span class="pre">primary_key=True</span></code>。更多细节请参见 <a class="reference internal" href="fields.html#django.db.models.AutoField" title="django.db.models.AutoField"><code class="xref py py-class docutils literal notranslate"><span class="pre">AutoField</span></code></a> 的文档。</p>
<div class="section" id="s-the-pk-property">
<span id="the-pk-property"></span><h4><code class="docutils literal notranslate"><span class="pre">pk</span></code> 属性<a class="headerlink" href="#the-pk-property" title="永久链接至标题">¶</a></h4>
<dl class="attribute">
<dt id="django.db.models.Model.pk">
<code class="descclassname">Model.</code><code class="descname">pk</code><a class="headerlink" href="#django.db.models.Model.pk" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>无论你是自己定义一个主键字段，还是让 Django 为你提供一个主键字段，每个模型都会有一个叫做 <code class="docutils literal notranslate"><span class="pre">pk</span></code> 的属性。它的行为就像模型上的一个普通属性，但实际上是模型主键字段属性的别名。您可以像读取和设置任何其他属性一样读取和设置这个值，它将更新模型中的正确字段。</p>
</div>
<div class="section" id="s-explicitly-specifying-auto-primary-key-values">
<span id="explicitly-specifying-auto-primary-key-values"></span><h4>明确指定自动主键值<a class="headerlink" href="#explicitly-specifying-auto-primary-key-values" title="永久链接至标题">¶</a></h4>
<p>如果一个模型有一个 <a class="reference internal" href="fields.html#django.db.models.AutoField" title="django.db.models.AutoField"><code class="xref py py-class docutils literal notranslate"><span class="pre">AutoField</span></code></a>，但你想在保存时显式地定义一个新对象的 ID，就在保存前显式地定义它，而不是依赖 ID 的自动分配：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">b3</span> <span class="o">=</span> <span class="n">Blog</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;Cheddar Talk&#39;</span><span class="p">,</span> <span class="n">tagline</span><span class="o">=</span><span class="s1">&#39;Thoughts on cheese.&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b3</span><span class="o">.</span><span class="n">id</span>     <span class="c1"># Returns 3.</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b3</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">b3</span><span class="o">.</span><span class="n">id</span>     <span class="c1"># Returns 3.</span>
</pre></div>
</div>
<p>如果你手动分配自动主键值，请确保不要使用一个已经存在的主键值！如果你创建一个新的对象，并使用一个已经存在于数据库中的显式主键值，Django 会认为你是在改变现有的记录，而不是创建一个新的记录。</p>
<p>考虑到上面的 <code class="docutils literal notranslate"><span class="pre">'Cheddar</span> <span class="pre">Talk'</span></code> 博客的例子，这个例子将覆盖数据库中以前的记录：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b4</span> <span class="o">=</span> <span class="n">Blog</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;Not Cheddar&#39;</span><span class="p">,</span> <span class="n">tagline</span><span class="o">=</span><span class="s1">&#39;Anything but cheese.&#39;</span><span class="p">)</span>
<span class="n">b4</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>  <span class="c1"># Overrides the previous blog with ID=3!</span>
</pre></div>
</div>
<p>发生这种情况的原因，请看下面 <a class="reference internal" href="#how-django-knows-to-update-vs-insert">How Django knows to UPDATE vs. INSERT</a> 。</p>
<p>明确指定自动主键值主要用于批量保存对象，当你确信不会发生主键碰撞时。</p>
<p>如果你使用的是 PostgreSQL，与主键相关的序列可能需要更新；参见 <a class="reference internal" href="../databases.html#manually-specified-autoincrement-pk"><span class="std std-ref">手动指定自增主键的值。</span></a>。</p>
</div>
</div>
<div class="section" id="s-what-happens-when-you-save">
<span id="what-happens-when-you-save"></span><h3>保存时会发生什么？<a class="headerlink" href="#what-happens-when-you-save" title="永久链接至标题">¶</a></h3>
<p>当你保存一个对象时，Django 会执行以下步骤：</p>
<ol class="arabic">
<li><p class="first"><strong>发送一个预保存信号。</strong> <a class="reference internal" href="../signals.html#django.db.models.signals.pre_save" title="django.db.models.signals.pre_save"><code class="xref py py-data docutils literal notranslate"><span class="pre">pre_save</span></code></a> 信号被发送，允许任何监听该信号的函数做一些事情。</p>
</li>
<li><p class="first"><strong>预处理数据。</strong> 每个字段的 <a class="reference internal" href="fields.html#django.db.models.Field.pre_save" title="django.db.models.Field.pre_save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">pre_save()</span></code></a> 方法被调用来执行任何需要的自动数据修改。例如，日期／时间字段重写了 <code class="docutils literal notranslate"><span class="pre">pre_save()</span></code> 来实现 <a class="reference internal" href="fields.html#django.db.models.DateField.auto_now_add" title="django.db.models.DateField.auto_now_add"><code class="xref py py-attr docutils literal notranslate"><span class="pre">auto_now_add</span></code></a> 和 <a class="reference internal" href="fields.html#django.db.models.DateField.auto_now" title="django.db.models.DateField.auto_now"><code class="xref py py-attr docutils literal notranslate"><span class="pre">auto_now</span></code></a>。</p>
</li>
<li><p class="first"><strong>为数据库准备数据。</strong> 要求每个字段的 <a class="reference internal" href="fields.html#django.db.models.Field.get_db_prep_save" title="django.db.models.Field.get_db_prep_save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get_db_prep_save()</span></code></a> 方法提供其当前的值，数据类型可以写入数据库。</p>
<p>大多数字段不需要数据准备。简单的数据类型，如整数和字符串，作为一个 Python 对象是“可以写入”的。然而，更复杂的数据类型通常需要一些修改。</p>
<p>例如，<a class="reference internal" href="fields.html#django.db.models.DateField" title="django.db.models.DateField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DateField</span></code></a> 字段使用 Python <code class="docutils literal notranslate"><span class="pre">datetime</span></code> 对象来存储数据。数据库不存储 <code class="docutils literal notranslate"><span class="pre">datetime</span></code> 对象，所以字段值必须转换成符合 ISO 标准的日期字符串才能插入数据库。</p>
</li>
<li><p class="first"><strong>将数据插入数据库。</strong> 将预先处理、准备好的数据组成 SQL 语句，以便插入数据库。</p>
</li>
<li><p class="first"><strong>发送一个保存后的信号。</strong> <a class="reference internal" href="../signals.html#django.db.models.signals.post_save" title="django.db.models.signals.post_save"><code class="xref py py-data docutils literal notranslate"><span class="pre">post_save</span></code></a> 信号被发送，允许任何监听该信号的函数做一些事情。</p>
</li>
</ol>
</div>
<div class="section" id="s-how-django-knows-to-update-vs-insert">
<span id="how-django-knows-to-update-vs-insert"></span><h3>Django 是如何知道 UPDATE 与 INSERT 的？<a class="headerlink" href="#how-django-knows-to-update-vs-insert" title="永久链接至标题">¶</a></h3>
<p>你可能已经注意到 Django 数据库对象使用相同的 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 方法来创建和更改对象。Django 抽象了需要使用 <code class="docutils literal notranslate"><span class="pre">INSERT</span></code> 或 <code class="docutils literal notranslate"><span class="pre">UPDATE</span></code> 的 SQL 语句。具体来说，当你调用 <code class="docutils literal notranslate"><span class="pre">save()</span></code>，而对象的主键属性 <strong>没有</strong> 定义一个 <a class="reference internal" href="fields.html#django.db.models.Field.default" title="django.db.models.Field.default"><code class="xref py py-attr docutils literal notranslate"><span class="pre">default</span></code></a> 时，Django 会遵循这个算法。</p>
<ul class="simple">
<li>如果对象的主键属性被设置为值为 <code class="docutils literal notranslate"><span class="pre">True</span></code> （即，一个不是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 或空字符串的值），Django 会执行 <code class="docutils literal notranslate"><span class="pre">UPDATE</span></code>。</li>
<li>如果对象的主键属性没有设置，或者 <code class="docutils literal notranslate"><span class="pre">UPDATE</span></code> 没有更新任何东西（例如主键被设置为数据库中不存在的值），Django 会执行 <code class="docutils literal notranslate"><span class="pre">INSERT</span></code>。</li>
</ul>
<p>如果对象的主键属性定义了一个 <a class="reference internal" href="fields.html#django.db.models.Field.default" title="django.db.models.Field.default"><code class="xref py py-attr docutils literal notranslate"><span class="pre">default</span></code></a>，那么如果它是一个现有的模型实例，并且主键被设置为数据库中存在的值，Django 就会执行一个 <code class="docutils literal notranslate"><span class="pre">UPDATE</span></code>。否则，Django 会执行一个 <code class="docutils literal notranslate"><span class="pre">INSERT</span></code>。</p>
<p>这里的一个问题是，如果你不能保证主键值未被使用，那么在保存新对象时，你应该注意不要显式地指定一个主键值。关于这个细微的差别，请看上面的 <a class="reference internal" href="#explicitly-specifying-auto-primary-key-values">Explicitly specifying auto-primary-key values</a> 和下面的 <a class="reference internal" href="#forcing-an-insert-or-update">Forcing an INSERT or UPDATE</a> 。</p>
<p>在 Django 1.5 和更早的版本中，当主键属性被设置时，Django 执行 <code class="docutils literal notranslate"><span class="pre">SELECT</span></code>。如果 <code class="docutils literal notranslate"><span class="pre">SELECT</span></code> 找到了一条记录，那么 Django 就会进行 <code class="docutils literal notranslate"><span class="pre">UPDATE</span></code>，否则就会进行 <code class="docutils literal notranslate"><span class="pre">INSERT</span></code>。老算法的结果是在 <code class="docutils literal notranslate"><span class="pre">UPDATE</span></code> 的情况下多了一个查询。在一些罕见的情况下，即使数据库中包含了一条对象主键值的记录，数据库也不会报告某行被更新。一个例子是 PostgreSQL 的 <code class="docutils literal notranslate"><span class="pre">ON</span> <span class="pre">UPDATE</span></code> 触发器，它返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。在这种情况下，可以通过将 <a class="reference internal" href="options.html#django.db.models.Options.select_on_save" title="django.db.models.Options.select_on_save"><code class="xref py py-attr docutils literal notranslate"><span class="pre">select_on_save</span></code></a> 选项设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 来恢复到旧算法。</p>
<div class="section" id="s-forcing-an-insert-or-update">
<span id="s-ref-models-force-insert"></span><span id="forcing-an-insert-or-update"></span><span id="ref-models-force-insert"></span><h4>强制执行 INSERT 或 UPDATE<a class="headerlink" href="#forcing-an-insert-or-update" title="永久链接至标题">¶</a></h4>
<p>在一些罕见的情况下，有必要强制 <a class="reference internal" href="#django.db.models.Model.save" title="django.db.models.Model.save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a> 方法执行 SQL <code class="docutils literal notranslate"><span class="pre">INSERT</span></code>，而不是回到 <code class="docutils literal notranslate"><span class="pre">UPDATE</span></code>。或者反过来说：如果可能的话，更新，但不插入新的记录。在这些情况下，你可以将 <code class="docutils literal notranslate"><span class="pre">force_insert=True</span></code> 或 <code class="docutils literal notranslate"><span class="pre">force_update=True</span></code> 参数传递给 <a class="reference internal" href="#django.db.models.Model.save" title="django.db.models.Model.save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a> 方法。传递这两个参数是一个错误：你不能同时插入 <em>和</em> 更新！</p>
<p>你应该很少需要使用这些参数。Django 几乎总是会做正确的事情，试图覆盖会导致难以追踪的错误。这个功能只适合进阶使用。</p>
<p>使用 <code class="docutils literal notranslate"><span class="pre">update_fields</span></code> 将强制更新，类似于 <code class="docutils literal notranslate"><span class="pre">force_update</span></code>。</p>
</div>
</div>
<div class="section" id="s-updating-attributes-based-on-existing-fields">
<span id="s-ref-models-field-updates-using-f-expressions"></span><span id="updating-attributes-based-on-existing-fields"></span><span id="ref-models-field-updates-using-f-expressions"></span><h3>基于现有字段更新属性<a class="headerlink" href="#updating-attributes-based-on-existing-fields" title="永久链接至标题">¶</a></h3>
<p>有时你需要在一个字段上执行一个简单的算术任务，比如递增或递减当前值。一种方法是在 Python 中进行运算，比如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">product</span> <span class="o">=</span> <span class="n">Product</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Venezuelan Beaver Cheese&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">product</span><span class="o">.</span><span class="n">number_sold</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">product</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p>如果从数据库中检索到的 <code class="docutils literal notranslate"><span class="pre">number_sold</span></code> 旧值是 10，那么 11 的值将被写回数据库。</p>
<p>这个过程可以变得更健壮， <a class="reference internal" href="expressions.html#avoiding-race-conditions-using-f"><span class="std std-ref">避免竞争条件</span></a>，以及通过表达相对于原始字段值的更新，而不是作为一个新值的显式赋值来稍微加快。Django 提供了 <a class="reference internal" href="expressions.html#django.db.models.F" title="django.db.models.F"><code class="xref py py-class docutils literal notranslate"><span class="pre">F</span> <span class="pre">表达式</span></code></a> 来执行这种相对更新。使用 <a class="reference internal" href="expressions.html#django.db.models.F" title="django.db.models.F"><code class="xref py py-class docutils literal notranslate"><span class="pre">F</span> <span class="pre">表达式</span></code></a>，前面的例子表示为：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">django.db.models</span> <span class="kn">import</span> <span class="n">F</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">product</span> <span class="o">=</span> <span class="n">Product</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Venezuelan Beaver Cheese&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">product</span><span class="o">.</span><span class="n">number_sold</span> <span class="o">=</span> <span class="n">F</span><span class="p">(</span><span class="s1">&#39;number_sold&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">product</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
<p>更多细节，请参阅 <a class="reference internal" href="expressions.html#django.db.models.F" title="django.db.models.F"><code class="xref py py-class docutils literal notranslate"><span class="pre">F</span> <span class="pre">表达式</span></code></a> 及其 <a class="reference internal" href="../../topics/db/queries.html#topics-db-queries-update"><span class="std std-ref">在更新查询中的使用</span></a> 的文档。</p>
</div>
<div class="section" id="s-specifying-which-fields-to-save">
<span id="specifying-which-fields-to-save"></span><h3>指定要保存的字段<a class="headerlink" href="#specifying-which-fields-to-save" title="永久链接至标题">¶</a></h3>
<p>如果 <code class="docutils literal notranslate"><span class="pre">save()</span></code> 在关键字参数 <code class="docutils literal notranslate"><span class="pre">update_fields</span></code> 中传递了一个字段名列表，那么只有列表中命名的字段才会被更新。如果你只想更新一个对象上的一个或几个字段，这可能是可取的。防止数据库中所有的模型字段被更新会有轻微的性能优势。例如：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">product</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s1">&#39;Name changed again&#39;</span>
<span class="n">product</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">update_fields</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">])</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">update_fields</span></code> 参数可以是任何包含字符串的可迭代对象。一个空的 <code class="docutils literal notranslate"><span class="pre">update_fields</span></code> 可迭代对象将跳过保存。值为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 将对所有字段进行更新。</p>
<p>指定 <code class="docutils literal notranslate"><span class="pre">update_fields</span></code> 将强制更新。</p>
<p>当保存一个通过延迟模型加载获取的模型时（<code class="xref py py-meth docutils literal notranslate"><span class="pre">only()</span></code> 或 <code class="xref py py-meth docutils literal notranslate"><span class="pre">defer()</span></code>），只有从数据库加载的字段会被更新。实际上，在这种情况下有一个自动的 <code class="docutils literal notranslate"><span class="pre">update_fields</span></code>。如果你分配或改变任何延迟字段的值，该字段将被添加到更新的字段中。</p>
</div>
</div>
<div class="section" id="s-deleting-objects">
<span id="deleting-objects"></span><h2>删除对象<a class="headerlink" href="#deleting-objects" title="永久链接至标题">¶</a></h2>
<dl class="method">
<dt id="django.db.models.Model.delete">
<code class="descclassname">Model.</code><code class="descname">delete</code>(<em>using=DEFAULT_DB_ALIAS</em>, <em>keep_parents=False</em>)<a class="headerlink" href="#django.db.models.Model.delete" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>为该对象发出一个 SQL <code class="docutils literal notranslate"><span class="pre">DELETE</span></code>。这只是删除数据库中的对象；Python 实例仍然存在，并且在其字段中仍然有数据。这个方法返回被删除的对象的数量和一个包含每个对象类型删除数量的字典。</p>
<p>更多细节，包括如何批量删除对象，请参见 <a class="reference internal" href="../../topics/db/queries.html#topics-db-queries-delete"><span class="std std-ref">Deleting objects</span></a>。</p>
<p>如果你想自定义删除行为，你可以覆盖 <code class="docutils literal notranslate"><span class="pre">delete()</span></code> 方法。更多细节请参见 <a class="reference internal" href="../../topics/db/models.html#overriding-model-methods"><span class="std std-ref">Overriding predefined model methods</span></a>。</p>
<p>有时，在 <a class="reference internal" href="../../topics/db/models.html#multi-table-inheritance"><span class="std std-ref">多表继承</span></a> 中，你可能只想删除子模型的数据，指定 <code class="docutils literal notranslate"><span class="pre">keep_parents=True</span></code> 将保留父模型的数据。指定 <code class="docutils literal notranslate"><span class="pre">keep_parents=True</span></code> 将保留父模型的数据。</p>
</div>
<div class="section" id="s-pickling-objects">
<span id="pickling-objects"></span><h2>Pickle 序列化对象<a class="headerlink" href="#pickling-objects" title="永久链接至标题">¶</a></h2>
<p>当你 <a class="reference external" href="https://docs.python.org/3/library/pickle.html#module-pickle" title="(在 Python v3.9)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">pickle</span></code></a> 一个模型时，它的当前状态被序列化。当你反序列化时，它将包含它被序列化时的模型实例，而不是当前数据库中的数据。</p>
<div class="admonition-you-can-t-share-pickles-between-versions admonition">
<p class="first admonition-title">你不能在不同版本之间共享 pickle</p>
<p>模型的 pickle 只对生成它们的 Django 版本有效。如果你使用 Django 版本 N 生成了一个 pickle，那么不能保证这个 pickle 在 Django 版本 N+1 中可以被读取。Pickle 不应该作为长期存档策略的一部分。</p>
<p class="last">由于 pickle 兼容性错误可能很难诊断，比如静默损坏对象，所以当你试图在 Django 版本中反序列化模型时，会发出 <code class="docutils literal notranslate"><span class="pre">RuntimeWarning</span></code> 的警告。</p>
</div>
</div>
<div class="section" id="s-other-model-instance-methods">
<span id="s-model-instance-methods"></span><span id="other-model-instance-methods"></span><span id="model-instance-methods"></span><h2>其他模型实例方法<a class="headerlink" href="#other-model-instance-methods" title="永久链接至标题">¶</a></h2>
<p>有几个对象方法有特殊用途。</p>
<div class="section" id="s-str">
<span id="str"></span><h3><code class="docutils literal notranslate"><span class="pre">__str__()</span></code><a class="headerlink" href="#str" title="永久链接至标题">¶</a></h3>
<dl class="method">
<dt id="django.db.models.Model.__str__">
<code class="descclassname">Model.</code><code class="descname">__str__</code>()<a class="headerlink" href="#django.db.models.Model.__str__" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>每当你对一个对象调用 <code class="docutils literal notranslate"><span class="pre">str()</span></code> 时，就会调用 <code class="docutils literal notranslate"><span class="pre">__str__()</span></code> 方法。Django 在很多地方使用了 <code class="docutils literal notranslate"><span class="pre">str(obj)</span></code> 方法。最主要的是，在 Django 管理站点中显示一个对象，以及作为模板显示对象时插入的值。因此，你应该总是从 <code class="docutils literal notranslate"><span class="pre">__str__()</span></code> 方法中返回一个漂亮的、人类可读的模型表示。</p>
<p>例子：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">first_name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">50</span><span class="p">)</span>
    <span class="n">last_name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">50</span><span class="p">)</span>

    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s1">&#39;</span><span class="si">%s</span><span class="s1"> </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">first_name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">last_name</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-eq">
<span id="eq"></span><h3><code class="docutils literal notranslate"><span class="pre">__eq__()</span></code><a class="headerlink" href="#eq" title="永久链接至标题">¶</a></h3>
<dl class="method">
<dt id="django.db.models.Model.__eq__">
<code class="descclassname">Model.</code><code class="descname">__eq__</code>()<a class="headerlink" href="#django.db.models.Model.__eq__" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>相等方法的定义是，具有相同主键值和相同具体类的实例被认为是相等的，但主键值为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 的实例除自身外对任何事物都不相等。对于代理模型，具体类被定义为模型的第一个非代理父类；对于所有其他模型，它只是模型的类。</p>
<p>例子：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">MyModel</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="nb">id</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">AutoField</span><span class="p">(</span><span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">MyProxyModel</span><span class="p">(</span><span class="n">MyModel</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
        <span class="n">proxy</span> <span class="o">=</span> <span class="kc">True</span>

<span class="k">class</span> <span class="nc">MultitableInherited</span><span class="p">(</span><span class="n">MyModel</span><span class="p">):</span>
    <span class="k">pass</span>

<span class="c1"># Primary keys compared</span>
<span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="c1"># Primary keys are None</span>
<span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="o">!=</span> <span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
<span class="c1"># Same instance</span>
<span class="n">instance</span> <span class="o">=</span> <span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
<span class="n">instance</span> <span class="o">==</span> <span class="n">instance</span>
<span class="c1"># Proxy model</span>
<span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="n">MyProxyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="c1"># Multi-table inheritance</span>
<span class="n">MyModel</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="n">MultitableInherited</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="s-hash">
<span id="hash"></span><h3><code class="docutils literal notranslate"><span class="pre">__hash__()</span></code><a class="headerlink" href="#hash" title="永久链接至标题">¶</a></h3>
<dl class="method">
<dt id="django.db.models.Model.__hash__">
<code class="descclassname">Model.</code><code class="descname">__hash__</code>()<a class="headerlink" href="#django.db.models.Model.__hash__" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p><code class="docutils literal notranslate"><span class="pre">__hash__()</span></code> 方法是基于实例的主键值。它实际上是 <code class="docutils literal notranslate"><span class="pre">hash(obj.pk)</span></code>。如果实例没有主键值，那么将引发一个 <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> （否则 <code class="docutils literal notranslate"><span class="pre">__hash__()</span></code> 方法会在保存实例之前和之后返回不同的值，但是在 Python 中禁止改变实例的 <a class="reference external" href="https://docs.python.org/3/reference/datamodel.html#object.__hash__" title="(在 Python v3.9)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__hash__()</span></code></a> 值。</p>
</div>
<div class="section" id="s-get-absolute-url">
<span id="get-absolute-url"></span><h3><code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code><a class="headerlink" href="#get-absolute-url" title="永久链接至标题">¶</a></h3>
<dl class="method">
<dt id="django.db.models.Model.get_absolute_url">
<code class="descclassname">Model.</code><code class="descname">get_absolute_url</code>()<a class="headerlink" href="#django.db.models.Model.get_absolute_url" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>定义一个 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code> 方法来告诉 Django 如何计算一个对象的标准 URL。对于调用者来说，这个方法应该返回一个字符串，可以通过 HTTP 引用对象。</p>
<p>例子：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_absolute_url</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="k">return</span> <span class="s2">&quot;/people/</span><span class="si">%i</span><span class="s2">/&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">id</span>
</pre></div>
</div>
<p>虽然这段代码正确且简单，但它可能不是写这种方法的最可移植的方式。<a class="reference internal" href="../urlresolvers.html#django.urls.reverse" title="django.urls.reverse"><code class="xref py py-func docutils literal notranslate"><span class="pre">reverse()</span></code></a> 函数通常是最好的方法。</p>
<p>例子：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_absolute_url</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="kn">from</span> <span class="nn">django.urls</span> <span class="kn">import</span> <span class="n">reverse</span>
    <span class="k">return</span> <span class="n">reverse</span><span class="p">(</span><span class="s1">&#39;people-detail&#39;</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;pk&#39;</span> <span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">pk</span><span class="p">})</span>
</pre></div>
</div>
<p>Django 使用 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code> 的一个地方就是在管理应用中。如果一个对象定义了这个方法，那么对象编辑页面会有一个“View on site”的链接，直接跳转到对象的公开视图，就像 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code> 给出的那样。</p>
<p>类似的，Django 的其他几个部分，比如 <a class="reference internal" href="../contrib/syndication.html"><span class="doc">联合供稿框架</span></a>，当定义了 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code> 时，也会使用 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code>。如果你的模型的每个实例都有一个唯一的 URL，你应该定义 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code>。</p>
<div class="admonition warning">
<p class="first admonition-title">警告</p>
<p>你应该避免从未经验证的用户输入中建立 URL，以减少链接或重定向中毒的可能性：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">get_absolute_url</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="k">return</span> <span class="s1">&#39;/</span><span class="si">%s</span><span class="s1">/&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
</pre></div>
</div>
<p class="last">如果 <code class="docutils literal notranslate"><span class="pre">self.name</span></code> 是 <code class="docutils literal notranslate"><span class="pre">'/example.com'</span></code>，这将返回 <code class="docutils literal notranslate"><span class="pre">'//example.com/'</span></code>，这反过来又是一个有效的协议相对 URL，但不是预期的 <code class="docutils literal notranslate"><span class="pre">'/%2Fexample.com/'</span></code>。</p>
</div>
<p>在模板中使用 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code>，而不是硬编码你的对象的 URL，这是一个很好的做法。例如，这个模板代码就很糟糕：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="c">&lt;!-- BAD template code. Avoid! --&gt;</span>
<span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;/people/</span><span class="cp">{{</span> <span class="nv">object.id</span> <span class="cp">}}</span><span class="s">/&quot;</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">object.name</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>这个模板代码就好多了：</p>
<div class="highlight-html+django notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">object.get_absolute_url</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">object.name</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>这里的逻辑是，如果你改变了你的对象的 URL 结构，即使是为了纠正拼写错误这样的小事，你也不想追踪 URL 可能被创建的每个地方。在 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code> 中指定一次，然后让你的其他代码调用那个地方。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p>从 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code> 返回的字符串 <strong>必须</strong> 只包含 ASCII 字符（URI 规范要求，<span class="target" id="index-2"></span><a class="rfc reference external" href="https://tools.ietf.org/html/rfc2396.html#section-2"><strong>RFC 2396#section-2</strong></a>），并在必要时进行 URL 编码。</p>
<p class="last">调用 <code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code> 的代码和模板应该可以直接使用结果，而不需要任何进一步的处理。如果你使用的字符串包含 ASCII 码范围以外的字符，你可能希望使用 <code class="docutils literal notranslate"><span class="pre">django.utils.encoding.iri_to_uri()</span></code> 函数来帮助解决这个问题。</p>
</div>
</div>
</div>
<div class="section" id="s-extra-instance-methods">
<span id="extra-instance-methods"></span><h2>额外的实例方法<a class="headerlink" href="#extra-instance-methods" title="永久链接至标题">¶</a></h2>
<p>除了 <a class="reference internal" href="#django.db.models.Model.save" title="django.db.models.Model.save"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a>、 <a class="reference internal" href="#django.db.models.Model.delete" title="django.db.models.Model.delete"><code class="xref py py-meth docutils literal notranslate"><span class="pre">delete()</span></code></a> 之外，一个模型对象还可能有以下一些方法：</p>
<dl class="method">
<dt id="django.db.models.Model.get_FOO_display">
<code class="descclassname">Model.</code><code class="descname">get_FOO_display</code>()<a class="headerlink" href="#django.db.models.Model.get_FOO_display" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>对于每一个设置了 <code class="xref py py-attr docutils literal notranslate"><span class="pre">choice</span></code> 的字段，该对象将有一个 <code class="docutils literal notranslate"><span class="pre">get_FOO_display()</span></code> 方法，其中 <code class="docutils literal notranslate"><span class="pre">FOO</span></code> 是字段的名称。该方法返回字段的“人类可读”值。</p>
<p>例子：</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">django.db</span> <span class="kn">import</span> <span class="n">models</span>

<span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span>
    <span class="n">SHIRT_SIZES</span> <span class="o">=</span> <span class="p">(</span>
        <span class="p">(</span><span class="s1">&#39;S&#39;</span><span class="p">,</span> <span class="s1">&#39;Small&#39;</span><span class="p">),</span>
        <span class="p">(</span><span class="s1">&#39;M&#39;</span><span class="p">,</span> <span class="s1">&#39;Medium&#39;</span><span class="p">),</span>
        <span class="p">(</span><span class="s1">&#39;L&#39;</span><span class="p">,</span> <span class="s1">&#39;Large&#39;</span><span class="p">),</span>
    <span class="p">)</span>
    <span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span>
    <span class="n">shirt_size</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">choices</span><span class="o">=</span><span class="n">SHIRT_SIZES</span><span class="p">)</span>
</pre></div>
</div>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">Person</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;Fred Flintstone&quot;</span><span class="p">,</span> <span class="n">shirt_size</span><span class="o">=</span><span class="s2">&quot;L&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">shirt_size</span>
<span class="go">&#39;L&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">get_shirt_size_display</span><span class="p">()</span>
<span class="go">&#39;Large&#39;</span>
</pre></div>
</div>
<div class="versionchanged">
<span class="title">Changed in Django 3.1:</span> <p>增加了对 <code class="xref py py-class docutils literal notranslate"><span class="pre">ArrayField</span></code> 和 <code class="xref py py-class docutils literal notranslate"><span class="pre">RangeField</span></code> 的支持。</p>
</div>
<dl class="method">
<dt id="django.db.models.Model.get_next_by_FOO">
<code class="descclassname">Model.</code><code class="descname">get_next_by_FOO</code>(<em>**kwargs</em>)<a class="headerlink" href="#django.db.models.Model.get_next_by_FOO" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<dl class="method">
<dt id="django.db.models.Model.get_previous_by_FOO">
<code class="descclassname">Model.</code><code class="descname">get_previous_by_FOO</code>(<em>**kwargs</em>)<a class="headerlink" href="#django.db.models.Model.get_previous_by_FOO" title="永久链接至目标">¶</a></dt>
<dd></dd></dl>

<p>对于每一个 <a class="reference internal" href="fields.html#django.db.models.DateField" title="django.db.models.DateField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DateField</span></code></a> 和 <a class="reference internal" href="fields.html#django.db.models.DateTimeField" title="django.db.models.DateTimeField"><code class="xref py py-class docutils literal notranslate"><span class="pre">DateTimeField</span></code></a> 没有 <code class="xref py py-attr docutils literal notranslate"><span class="pre">null=True</span></code>，该对象将有 <code class="docutils literal notranslate"><span class="pre">get_next_by_FOO()</span></code> 和 <code class="docutils literal notranslate"><span class="pre">get_previous_by_FOO()</span></code> 方法，其中 <code class="docutils literal notranslate"><span class="pre">FOO</span></code> 是字段名。这将返回与日期字段相关的下一个和上一个对象，适当时引发一个 <a class="reference internal" href="class.html#django.db.models.Model.DoesNotExist" title="django.db.models.Model.DoesNotExist"><code class="xref py py-exc docutils literal notranslate"><span class="pre">DoesNotExist</span></code></a> 异常。</p>
<p>这两种方法都将使用模型的默认管理器执行查询。如果你需要模拟自定义管理器使用的过滤，或者想要执行一次性的自定义过滤，这两种方法也都接受可选的关键字参数，其格式应该是 <a class="reference internal" href="querysets.html#field-lookups"><span class="std std-ref">字段查找</span></a> 中描述的格式。</p>
<p>请注意，在日期值相同的情况下，这些方法将使用主键作为比较。这保证了没有记录被跳过或重复。这也意味着你不能对未保存的对象使用这些方法。</p>
<div class="admonition-overriding-extra-instance-methods admonition">
<p class="first admonition-title">覆盖额外的实例方法</p>
<p class="last">在大多数情况下，覆盖或继承 <code class="docutils literal notranslate"><span class="pre">get_FOO_display()</span></code>、<code class="docutils literal notranslate"><span class="pre">get_next_by_FOO()</span></code> 和 <code class="docutils literal notranslate"><span class="pre">get_previous_by_FOO()</span></code> 应按预期工作。然而，由于它们是由元类添加的，所以要考虑所有可能的继承结构是不实际的。在更复杂的情况下，你应该覆盖 <code class="docutils literal notranslate"><span class="pre">Field.contribution_to_class()</span></code> 来设置你需要的方法。</p>
</div>
</div>
<div class="section" id="s-other-attributes">
<span id="other-attributes"></span><h2>其他属性<a class="headerlink" href="#other-attributes" title="永久链接至标题">¶</a></h2>
<div class="section" id="s-state">
<span id="state"></span><h3><code class="docutils literal notranslate"><span class="pre">_state</span></code><a class="headerlink" href="#state" title="永久链接至标题">¶</a></h3>
<dl class="attribute">
<dt id="django.db.models.Model._state">
<code class="descclassname">Model.</code><code class="descname">_state</code><a class="headerlink" href="#django.db.models.Model._state" title="永久链接至目标">¶</a></dt>
<dd><p><code class="docutils literal notranslate"><span class="pre">_state</span></code> 属性指的是一个 <code class="docutils literal notranslate"><span class="pre">ModelState</span></code> 对象，它跟踪模型实例的生命周期。</p>
<p><code class="docutils literal notranslate"><span class="pre">ModelState</span></code> 对象有两个属性。<code class="docutils literal notranslate"><span class="pre">adding</span></code> 是一个标志，如果模型尚未保存到数据库，则为 <code class="docutils literal notranslate"><span class="pre">True</span></code>；<code class="docutils literal notranslate"><span class="pre">db</span></code> 是一个字符串，指的是实例从数据库加载或保存到的别名。</p>
<p>新实例有 <code class="docutils literal notranslate"><span class="pre">adding=True</span></code> 和 <code class="docutils literal notranslate"><span class="pre">db=None</span></code>，因为它们尚未被保存。从 <code class="docutils literal notranslate"><span class="pre">QuerySet</span></code> 获取的实例将有 <code class="docutils literal notranslate"><span class="pre">adding=False</span></code> 和 <code class="docutils literal notranslate"><span class="pre">db</span></code> 设置为相关数据库的别名。</p>
</dd></dl>

</div>
</div>
</div>


          </div>
        </div>
      </div>
      
        
          <div class="yui-b" id="sidebar">
            
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">模型实例参考</a><ul>
<li><a class="reference internal" href="#creating-objects">创建对象</a><ul>
<li><a class="reference internal" href="#customizing-model-loading">自定义模型加载</a></li>
</ul>
</li>
<li><a class="reference internal" href="#refreshing-objects-from-database">从数据库中刷新对象</a></li>
<li><a class="reference internal" href="#validating-objects">验证对象</a></li>
<li><a class="reference internal" href="#saving-objects">保存对象</a><ul>
<li><a class="reference internal" href="#auto-incrementing-primary-keys">自增主键</a><ul>
<li><a class="reference internal" href="#the-pk-property"><code class="docutils literal notranslate"><span class="pre">pk</span></code> 属性</a></li>
<li><a class="reference internal" href="#explicitly-specifying-auto-primary-key-values">明确指定自动主键值</a></li>
</ul>
</li>
<li><a class="reference internal" href="#what-happens-when-you-save">保存时会发生什么？</a></li>
<li><a class="reference internal" href="#how-django-knows-to-update-vs-insert">Django 是如何知道 UPDATE 与 INSERT 的？</a><ul>
<li><a class="reference internal" href="#forcing-an-insert-or-update">强制执行 INSERT 或 UPDATE</a></li>
</ul>
</li>
<li><a class="reference internal" href="#updating-attributes-based-on-existing-fields">基于现有字段更新属性</a></li>
<li><a class="reference internal" href="#specifying-which-fields-to-save">指定要保存的字段</a></li>
</ul>
</li>
<li><a class="reference internal" href="#deleting-objects">删除对象</a></li>
<li><a class="reference internal" href="#pickling-objects">Pickle 序列化对象</a></li>
<li><a class="reference internal" href="#other-model-instance-methods">其他模型实例方法</a><ul>
<li><a class="reference internal" href="#str"><code class="docutils literal notranslate"><span class="pre">__str__()</span></code></a></li>
<li><a class="reference internal" href="#eq"><code class="docutils literal notranslate"><span class="pre">__eq__()</span></code></a></li>
<li><a class="reference internal" href="#hash"><code class="docutils literal notranslate"><span class="pre">__hash__()</span></code></a></li>
<li><a class="reference internal" href="#get-absolute-url"><code class="docutils literal notranslate"><span class="pre">get_absolute_url()</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#extra-instance-methods">额外的实例方法</a></li>
<li><a class="reference internal" href="#other-attributes">其他属性</a><ul>
<li><a class="reference internal" href="#state"><code class="docutils literal notranslate"><span class="pre">_state</span></code></a></li>
</ul>
</li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="options.html"
                        title="上一章">模型 <code class="docutils literal notranslate"><span class="pre">Meta</span></code> 选项</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="querysets.html"
                        title="下一章"><code class="docutils literal notranslate"><span class="pre">QuerySet</span></code> API 参考</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../../_sources/ref/models/instances.txt"
            rel="nofollow">显示源代码</a></li>
    </ul>
   </div>
<div id="searchbox" style="display: none" role="search">
  <h3>快速搜索</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="转向" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    </div>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
              <h3>Last update:</h3>
              <p class="topless">7月 23, 2021</p>
          </div>
        
      
    </div>

    <div id="ft">
      <div class="nav">
    &laquo; <a href="options.html" title="模型 &lt;code class=&#34;docutils literal notranslate&#34;&gt;&lt;span class=&#34;pre&#34;&gt;Meta&lt;/span&gt;&lt;/code&gt; 选项">previous</a>
     |
    <a href="../index.html" title="API 参考" accesskey="U">up</a>
   |
    <a href="querysets.html" title="&lt;code class=&#34;docutils literal notranslate&#34;&gt;&lt;span class=&#34;pre&#34;&gt;QuerySet&lt;/span&gt;&lt;/code&gt; API 参考">next</a> &raquo;</div>
    </div>
  </div>

      <div class="clearer"></div>
    </div>
  </body>
</html>